/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef PLGDT_H
#define PLGDT_H

#include <stddef.h>
#include <machine/pc/processor/x86/taskstatesegment.h>

#include <tools/PLSingleton.h>
using namespace PLSDK;

/**
 * Manage the global description table.
 *
 * @todo Make a loop for all processors.
 */
class PLGDT : public PLSingleton<PLGDT> {
	friend class PLSingleton<PLGDT>;
public:
	/**
	 * Init the global description table.
	 */
	void init();
	/**
	 * Set the global description table.
	 */
	void set();
protected:
	/**
	 * Constructor.
	 */
	PLGDT();
private:
	void setSegmentDescriptor(size_t index, uint32_t base, uint32_t limit, uint8_t flags, uint8_t flags2);
	void initialiseTss(TaskStateSegment *pTss);
	void setTssDescriptor(size_t index, uint32_t base);
	void initialiseDoubleFaultTss(TaskStateSegment *pTss);
	struct segmentDescriptor {
		// Bits 0-15 from the limit
		uint16_t limit0;
		// Bits 0-15 from the base address
		uint16_t base0;
		// Bits 16-23 from the base address
		uint8_t base1;
		// The flags
		uint8_t flags;
		// Additional flags and bits 16-19 from the limit
		uint8_t flagsLimit1;
		// Bits 24-32 from the base address
		uint8_t base2;
	} PACKED;
	segmentDescriptor *m_gdt;
	size_t m_descriptorCount;
};

#endif // PLGDT_H
